package pe.com.bbva.ge.negocio.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.collections.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import pe.com.bbva.ge.domain.base.Identificador;
import pe.com.bbva.ge.domain.configuracion.Atm;
import pe.com.bbva.ge.domain.configuracion.Casetera;
import pe.com.bbva.ge.domain.configuracion.Denominacion;
import pe.com.bbva.ge.domain.configuracion.Lista;
import pe.com.bbva.ge.domain.configuracion.Parametro;
import pe.com.bbva.ge.domain.configuracion.Posicion;
import pe.com.bbva.ge.domain.configuracion.Regla;
import pe.com.bbva.ge.domain.configuracion.Transportadora;
import pe.com.bbva.ge.domain.configuracion.Valor;
import pe.com.bbva.ge.domain.quartz.QrtzCronTriggers;
import pe.com.bbva.ge.domain.quartz.QrtzJobDetails;
import pe.com.bbva.ge.domain.quartz.QrtzTriggers;
import pe.com.bbva.ge.domain.seguridad.Membresia;
import pe.com.bbva.ge.domain.seguridad.Opcion;
import pe.com.bbva.ge.domain.seguridad.Permiso;
import pe.com.bbva.ge.domain.seguridad.Rol;
import pe.com.bbva.ge.domain.solicitud.TipoSolicitud;
import pe.com.bbva.ge.negocio.ConfiguracionNegocio;
import pe.com.bbva.ge.persistencia.orm.ConfiguracionORM;
import pe.com.bbva.ge.utileria.Constante;

@Service
public class ConfiguracionNegocioImpl extends CrudNegocioImpl implements ConfiguracionNegocio {

	/**
	 * 
	 */
	private static final long serialVersionUID = -449723142842692419L;

	@Autowired
	private ConfiguracionORM genericoORM;
	
	@Override
	public Object obtenerNotificaciones() {
		return null;
	}

	@Override
	public List<Valor> obtenerValores(String codigoLista) {
		return genericoORM.obtenerValores(codigoLista);
	}

	@Override
	public List<Denominacion> obtenerDenominaciones(Valor moneda, Valor tipo) {
		
		return genericoORM.obtenerDenominaciones(moneda, tipo);
	}

	@Override
	public List<Denominacion> obtenerDenominaciones(Valor divisa) {
		return obtenerDenominaciones(divisa, null);
	}

	@Override
	public Valor obtenerValor(String codigoLista, String codigoValor) {
		return genericoORM.obtenerValor(codigoLista, codigoValor);
	}

	@Override
	public List<QrtzCronTriggers> buscarCronTriggers(
			QrtzCronTriggers qrtzCronTriggers) {
		return genericoORM.buscarCronTriggers(qrtzCronTriggers);
	}

	@Override
	public List<QrtzJobDetails> buscarJobDetails(QrtzJobDetails qrtzJobDetails) {
		return genericoORM.buscarJobDetails(qrtzJobDetails);
	}

	@Override
	public List<QrtzTriggers> buscarTriggers(QrtzTriggers qrtzTriggers) {
		return genericoORM.buscarTriggers(qrtzTriggers);
	}

	@Override
	public List<Posicion> obtenerPosicones(Valor TipoOrigenDestino) {
		return genericoORM.obtenerPosicones(TipoOrigenDestino);
	}

	@Override
	public List<TipoSolicitud> obtenerTipoSolicitud() {
		return genericoORM.obtenerTipoSolicitud();
	}

	@Override
	public List<Atm> obtenerListaATM() {
		return genericoORM.obtenerListaATM();
	}

	@Override
	public List<Casetera> obtenerListaCaseteras(Atm atm) {
		return genericoORM.obtenerListaCaseteras(atm);
	}
	
	@Override
	public <Entidad> Entidad obtenerEntidadPorCodigo(
			Identificador identificador, Class<Entidad> clase) {
		return genericoORM.obtenerEntidadPorCodigo(identificador, clase);
	}

	@Override
	public List<Transportadora> obtenerListaTransportadoras() {
		return genericoORM.obtenerListaTransportadoras();
	}

	@Override
	public List<Lista> buscarListas(Lista lista) {
		return genericoORM.buscarListas(lista);
	}

	@Override
	public List<Valor> buscarValores(Valor valor) {
		return genericoORM.buscarValores(valor);
	}

	@Override
	public Parametro obtenerParametroxCodigo(String codigo) {
		return genericoORM.obtenerParametroxCodigo(codigo);
	}

	@Override
	public List<Opcion> buscarOpciones(Opcion opcion) {
		return genericoORM.buscarOpciones(opcion);
	}

	@Override
	public Map<String, List<Opcion>> listarOpciones() {
		return genericoORM.listarOpciones();
	}

	@Override
	public List<Parametro> buscarParametros(Parametro parametro)
	{
		return genericoORM.buscarParametros(parametro);
	}

	@Override
	public List<Rol> buscarRoles(Rol rol) {
		return genericoORM.buscarRoles(rol);
	}

	@Override
	public List<Permiso> obtenerPermisosXRol(Long idRol, boolean estadoActivo) {
		return genericoORM.obtenerPermisosXRol(idRol, estadoActivo);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void guardarPermisos(Long idRol, List<Long> idsOpciones) {
		List<Permiso> permisosALL = obtenerPermisosXRol(idRol, false);
		List<Permiso> permisosA = obtenerPermisosXRol(idRol, true);
		List<Permiso> permisosSel = new ArrayList<Permiso>();
		for (Long idOpcion : idsOpciones) {
			Permiso permiso = new Permiso();
			permiso.setRol(new Rol());
			permiso.getRol().setId(idRol);
			permiso.setOpcion(new Opcion());
			permiso.getOpcion().setId(idOpcion);
			permisosSel.add(permiso);
		}
		List<Permiso> permisosD = ListUtils.subtract(permisosALL, permisosA);
		
		List<Permiso> updPermisosD = ListUtils.subtract(permisosA, permisosSel);
		List<Permiso> updPermisosA = ListUtils.intersection(permisosSel, permisosD);
		List<Permiso> insPermisosA = ListUtils.subtract(permisosSel, permisosALL);
		
		Valor estadoInactivo = obtenerValor(Constante.LISTA.CODIGO.REGISTRO_ESTADO, Constante.VALOR.REGISTRO_ESTADO.CODIGO.INACTIVO);
		Valor estadoActivo = obtenerValor(Constante.LISTA.CODIGO.REGISTRO_ESTADO, Constante.VALOR.REGISTRO_ESTADO.CODIGO.ACTIVO);
		
		prepararLista(updPermisosD, estadoInactivo);
		prepararLista(updPermisosA, estadoActivo);
		prepararLista(insPermisosA, estadoActivo);
		
		List<Permiso> permisosU = ListUtils.union(updPermisosD, updPermisosA);
		List<Permiso> permisos = ListUtils.union(permisosU, insPermisosA);
		
		grabarTodos(permisos);
	}
	
	private void prepararLista(List<Permiso> lista, Valor estado)
	{
		for (Permiso permiso : lista) {
			permiso.setEstado(estado);
		}
	}

	@Override
	public List<Rol> obtenerRolesHijo(Rol rol) {
		return genericoORM.obtenerRolesHijo(rol);
	}

	@Override
	public List<Membresia> buscarMembresias(Membresia membresia) {
		return genericoORM.buscarMembresias(membresia);
	}

	@Override
	public List<Atm> obtenerAtmsPorProveedor(Posicion posicionDestino) {
		return genericoORM.obtenerAtmsPorProveedor(posicionDestino);
	}

	@Override
	public int[] obtenerDimensionesAtmPorCasetera(Posicion posicionDestino) {
		
		Set<Denominacion> denominaciones = new TreeSet<Denominacion>();
		List<Atm> atms = obtenerAtmsPorProveedor(posicionDestino);
		
		/*for (Atm atm : atms) {
			//atm.getCodigo()
			for (Casetera casetera : atm.getCaseteras()) {
				//casetera.getCodigo()
				denominaciones.add(casetera.getDenominacion());
			}
		}*/
		
		return new int[]{denominaciones.size(), atms.size()};
	}

	@Override
	public List<Casetera> obtenerCaseterasPorProveedor(Posicion posicionDestino) {
		return genericoORM.obtenerCaseterasPorProveedor(posicionDestino);
	}

	@Override
	public List<Regla> buscarReglas(Regla regla) {
		return genericoORM.buscarReglas(regla);
	}
}
